﻿// Decompiled with JetBrains decompiler
// Type: NetickEditor.NetworkBehaviourEditor
// Assembly: Netick.Unity.Editor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 0658BB4A-05C4-428D-9BD6-82E94959F5A1
// Assembly location: D:\WorkSpaceDemo\UPM\NetickForUnity\Netick\Editor\Netick.Unity.Editor.dll

using Netick;
using Netick.Unity;
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;

#nullable disable
namespace NetickEditor;

[CustomEditor(typeof (NetworkBehaviour), true)]
[CanEditMultipleObjects]
public class NetworkBehaviourEditor : Editor
{
  private NetworkBehaviour _behaviour;
  private List<DrawnProperty> _networkedProperties = new List<DrawnProperty>(10);
  private DrawnArrayItem[] _arrays = new DrawnArrayItem[0];
  private GUIContent _varIcon;
  private Vector2 _margin = new Vector2(2f, 10f);

  public virtual void OnEnable()
  {
    if (this.target == (UnityEngine.Object) null)
      return;
    this._varIcon = EditorGUIUtility.IconContent("sv_icon_dot1_pix16_gizmo");
    this._behaviour = (NetworkBehaviour) this.target;
    System.Type type = ((object) this._behaviour).GetType();
    this._networkedProperties.Clear();
    List<DrawnArrayItem> drawnArrayItemList = new List<DrawnArrayItem>(32 /*0x20*/);
    foreach (FieldInfo field in type.GetFields())
    {
      if (Attribute.IsDefined((MemberInfo) field, typeof (Networked)) && field.FieldType.Name.Contains("Array"))
      {
        SerializedProperty property = this.serializedObject.FindProperty(field.Name + "._array");
        NetworkArray networkArray = (NetworkArray) field.GetValue((object) this._behaviour);
        drawnArrayItemList.Add(new DrawnArrayItem()
        {
          NetArray = networkArray,
          CollectionType = CollectionType.Array,
          Element = property,
          Name = field.Name,
          Folded = true
        });
      }
    }
    this._arrays = drawnArrayItemList.ToArray();
    SerializedProperty iterator = this.serializedObject.GetIterator();
    if (!iterator.Next(true))
      return;
    do
    {
      string name = iterator.name.Replace(">k__BackingField", "").Replace("<", "");
      PropertyInfo property = type.GetProperty(name);
      if (!(property == (PropertyInfo) null) && Attribute.IsDefined((MemberInfo) property, typeof (Networked)))
      {
        FieldInfo backingField = this.GetBackingField((object) this._behaviour, property.Name);
        this._networkedProperties.Add(new DrawnProperty()
        {
          SerializedProperty = iterator.Copy(),
          BackingField = backingField,
          Property = property
        });
      }
    }
    while (iterator.Next(false));
  }

  public virtual unsafe void OnInspectorGUI()
  {
    this.serializedObject.Update();
    NetworkBehaviour targetObject = (NetworkBehaviour) this.serializedObject.targetObject;
    if (Application.isPlaying && targetObject.gameObject.activeInHierarchy && (UnityEngine.Object) targetObject.Object == (UnityEngine.Object) null)
    {
      Color color = GUI.color;
      GUI.color = Color.yellow;
      GUI.color = color;
    }
    if ((IntPtr) targetObject.StatePtr != IntPtr.Zero)
    {
      this.DrawPropertiesRuntime();
      this.DrawArraysRuntime();
    }
    else
    {
      this.DrawPropertiesEditor();
      this.DrawArraysEditor();
    }
    this.serializedObject.ApplyModifiedProperties();
    NetworkBehaviourEditor.HorizontalLine(Color.gray, 0.4f, this._margin);
    this.DrawDefaultInspector();
  }

  private void DrawArraysEditor()
  {
    for (int index = 0; index < this._arrays.Length; ++index)
    {
      try
      {
        EditorGUILayout.PropertyField(this._arrays[index].Element, new GUIContent(this._arrays[index].Name), true, Array.Empty<GUILayoutOption>());
      }
      catch (Exception ex)
      {
      }
    }
  }

  private void DrawArraysRuntime()
  {
    for (int index1 = 0; index1 < this._arrays.Length; ++index1)
    {
      DrawnArrayItem array = this._arrays[index1];
      int length = array.NetArray.Length;
      bool flag = EditorGUILayout.BeginFoldoutHeaderGroup(this._arrays[index1].Folded, this._arrays[index1].Name, (GUIStyle) null, (Action<Rect>) null, (GUIStyle) null);
      this._arrays[index1].Folded = flag;
      if (flag)
      {
        EditorGUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
        for (int index2 = 0; index2 < length; ++index2)
        {
          EditorGUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
          GUILayout.Label(this._varIcon, GUILayout.Width(17f), GUILayout.Height(17f));
          EditorGUILayout.LabelField($"{index2}", array.NetArray.PrintValue(index2), Array.Empty<GUILayoutOption>());
          EditorGUILayout.EndHorizontal();
        }
        EditorGUILayout.EndVertical();
      }
      EditorGUILayout.EndFoldoutHeaderGroup();
    }
  }

  private void DrawPropertiesRuntime()
  {
    for (int index = 0; index < this._networkedProperties.Count; ++index)
    {
      try
      {
        EditorGUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
        GUILayout.Label(this._varIcon, GUILayout.Width(17f), GUILayout.Height(17f));
        DrawnProperty networkedProperty = this._networkedProperties[index];
        this.DrawPropertyRuntime(this._networkedProperties[index].Property);
        EditorGUILayout.EndHorizontal();
      }
      catch (Exception ex)
      {
        EditorGUILayout.EndHorizontal();
      }
    }
  }

  private void DrawPropertiesEditor()
  {
    for (int index = 0; index < this._networkedProperties.Count; ++index)
    {
      if (this._networkedProperties[index].SerializedProperty != null)
        this.DrawPropertyEditor(this._networkedProperties[index].SerializedProperty);
    }
  }

  internal static void HorizontalLine(Color color, float height, Vector2 margin)
  {
    GUILayout.Space(margin.x);
    EditorGUI.DrawRect(EditorGUILayout.GetControlRect(false, height, Array.Empty<GUILayoutOption>()), color);
    GUILayout.Space(margin.y);
  }

  private object DrawPropertyRuntime(PropertyInfo property)
  {
    string name = property.Name;
    object obj1 = (object) null;
    if (property.PropertyType == typeof (Color))
      obj1 = (object) EditorGUILayout.ColorField(name, (Color) property.GetValue((object) this._behaviour, (object[]) null), Array.Empty<GUILayoutOption>());
    else if (property.PropertyType == typeof (Vector2))
      obj1 = (object) EditorGUILayout.Vector2Field(name, (Vector2) property.GetValue((object) this._behaviour, (object[]) null), Array.Empty<GUILayoutOption>());
    else if (property.PropertyType == typeof (Vector3))
      obj1 = (object) EditorGUILayout.Vector3Field(name, (Vector3) property.GetValue((object) this._behaviour, (object[]) null), Array.Empty<GUILayoutOption>());
    else if (property.PropertyType == typeof (Vector4))
      obj1 = (object) EditorGUILayout.Vector4Field(name, (Vector4) property.GetValue((object) this._behaviour, (object[]) null), Array.Empty<GUILayoutOption>());
    else if (property.PropertyType == typeof (Angle))
      obj1 = (object) EditorGUILayout.FloatField(name, ((Angle) property.GetValue((object) this._behaviour, (object[]) null)).Value, Array.Empty<GUILayoutOption>());
    else if (property.PropertyType == typeof (Quaternion))
    {
      Quaternion quaternion = (Quaternion) property.GetValue((object) this._behaviour, (object[]) null);
      obj1 = (object) EditorGUILayout.Vector4Field(name, new Vector4(quaternion.x, quaternion.y, quaternion.z, quaternion.w), Array.Empty<GUILayoutOption>());
    }
    else if (property.PropertyType == typeof (Tick))
      obj1 = (object) EditorGUILayout.IntField(name, ((Tick) property.GetValue((object) this._behaviour, (object[]) null)).Value, Array.Empty<GUILayoutOption>());
    else if (property.PropertyType == typeof (NetworkBool))
      EditorGUILayout.Toggle(name, (bool) (NetworkBool) property.GetValue((object) this._behaviour, (object[]) null), Array.Empty<GUILayoutOption>());
    else if (property.PropertyType == typeof (NetworkObjectRef))
    {
      NetworkObject networkObject;
      this._behaviour.Sandbox.TryGetObject((NetworkObjectRef) property.GetValue((object) this._behaviour, (object[]) null), out networkObject);
      EditorGUILayout.ObjectField(name, (UnityEngine.Object) networkObject, typeof (NetworkObject), true, Array.Empty<GUILayoutOption>());
    }
    else if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof (NetworkBehaviourRef<>))
    {
      object obj2 = property.GetValue((object) this._behaviour);
      System.Type type = obj2.GetType();
      FieldInfo field1 = type.GetField("ObjectId");
      FieldInfo field2 = type.GetField("BehaviourId");
      int id1 = (int) field1.GetValue(obj2);
      object obj3 = obj2;
      int id2 = (int) field2.GetValue(obj3);
      NetworkObject networkObject;
      this._behaviour.Sandbox.TryGetObject(id1, out networkObject);
      NetworkBehaviour networkBehaviour = (NetworkBehaviour) null;
      if ((UnityEngine.Object) networkObject != (UnityEngine.Object) null && id2 < networkObject.NetworkedBehaviours.Length)
        networkBehaviour = networkObject?.GetBehaviourById<NetworkBehaviour>(id2);
      EditorGUILayout.ObjectField(name, (UnityEngine.Object) networkBehaviour, typeof (NetworkBehaviour), true, Array.Empty<GUILayoutOption>());
    }
    else if (property.PropertyType == typeof (Guid))
      EditorGUILayout.LabelField(name, ((Guid) property.GetValue((object) this._behaviour, (object[]) null)).ToString(), Array.Empty<GUILayoutOption>());
    else if (property.PropertyType == typeof (string))
    {
      EditorGUILayout.LabelField(name, (string) property.GetValue((object) this._behaviour, (object[]) null), Array.Empty<GUILayoutOption>());
    }
    else
    {
      object obj4 = property.GetValue((object) this._behaviour, (object[]) null);
      if (obj4 != null)
        EditorGUILayout.LabelField(name, obj4.ToString(), Array.Empty<GUILayoutOption>());
    }
    return obj1;
  }

  private unsafe void DrawPropertyEditor(SerializedProperty property)
  {
    EditorGUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
    GUILayout.Label(this._varIcon, GUILayout.Width(17f), GUILayout.Height(17f));
    if (property.type == typeof (Tick).Name)
    {
      SerializedProperty propertyRelative = property.FindPropertyRelative("Value");
      int intValue = propertyRelative.intValue;
      propertyRelative.intValue = EditorGUILayout.IntField(property.displayName, intValue, Array.Empty<GUILayoutOption>());
    }
    else if (property.type == typeof (NetworkBool).Name)
    {
      SerializedProperty propertyRelative = property.FindPropertyRelative("RawValue");
      int intValue = propertyRelative.intValue;
      propertyRelative.intValue = EditorGUILayout.Toggle(property.displayName, intValue == 1, Array.Empty<GUILayoutOption>()) ? 1 : 0;
    }
    else if (property.type == typeof (Angle).Name)
    {
      SerializedProperty propertyRelative = property.FindPropertyRelative("_rawValue");
      float num = NetickUnityUtils.GetFloat(&propertyRelative.intValue, 1f / 1000f);
      propertyRelative.intValue = new Angle(EditorGUILayout.FloatField(property.displayName, num, Array.Empty<GUILayoutOption>()))._rawValue;
    }
    else if (property.type == typeof (NetworkObjectRef).Name)
      EditorGUILayout.LabelField(property.displayName, "Can only be set at runtime", Array.Empty<GUILayoutOption>());
    else if (property.type == typeof (NetworkBehaviourRef<>).Name)
      EditorGUILayout.LabelField(property.displayName, "Can only be set at runtime", Array.Empty<GUILayoutOption>());
    else
      EditorGUILayout.PropertyField(property, Array.Empty<GUILayoutOption>());
    EditorGUILayout.EndHorizontal();
  }

  private string GetBackingFieldName(string propertyName) => $"<{propertyName}>k__BackingField";

  private FieldInfo GetBackingField(object obj, string propertyName)
  {
    return obj.GetType().GetField(this.GetBackingFieldName(propertyName), BindingFlags.Instance | BindingFlags.NonPublic);
  }
}
